package com.alex.httphack.domain;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.zip.GZIPInputStream;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.util.ByteArrayBuffer;

import com.alex.common.ILogger;

public final class HttpResponseHack implements ILogger {

	private byte[] body;

	private Charset charset;

	private Header[] headers;

	private int statusCode;

	public HttpResponseHack(HttpResponse httpResponse)
			throws IllegalStateException, IOException {
		this.statusCode = httpResponse.getStatusLine().getStatusCode();
		init(httpResponse);
	}

	public int getStatusCode() {
		return this.statusCode;
	}

	public String getHeaderStr() {
		StringBuilder sb = new StringBuilder();
		for (Header header : headers) {
			sb.append(header.toString());
			sb.append(RN);
		}
		return sb.toString();
	}

	private void init(HttpResponse response) throws IllegalStateException,
			IOException {
		HttpEntity entity = response.getEntity();

		if (getStatusCode() == HttpStatus.SC_OK) {

			InputStream in = null;
			try {
				if (entity == null)
					throw new IllegalArgumentException(
							"HTTP entity may not be null");
				in = entity.getContent();
				if (in == null)
					this.body = new byte[] {};
				if (entity.getContentLength() > 2147483647L)
					throw new IllegalArgumentException(
							"HTTP entity too large to be buffered in memory");

				int i = (int) entity.getContentLength();
				if (i < 0) {
					i = 4096;
				}
				if (entity.getContentEncoding() != null
						&& "gzip".equalsIgnoreCase(entity.getContentEncoding()
								.getValue())) {
					// is gzip
					in = new GZIPInputStream(in);
					response.removeHeaders(HttpHeaders.CONTENT_ENCODING);
					response.removeHeaders(HttpHeaders.CONTENT_LENGTH);
					i = 4096;
				}

				ByteArrayBuffer buffer = new ByteArrayBuffer(i);
				byte tmp[] = new byte[i];
				int l;
				while ((l = in.read(tmp)) != -1)
					buffer.append(tmp, 0, l);
				this.body = buffer.toByteArray();
			} finally {
				if (in != null)
					in.close();
			}
		} else {
			this.body = response.getStatusLine().getReasonPhrase().getBytes();
		}

		this.headers = response.getAllHeaders();
		this.charset = parseCharset(entity.getContentType());
		// ContentType.get(entity).getCharset();// for
		// <httpclient.version>4.2.5</httpclient.version>
	}

	private Charset parseCharset(Header header) {
		if (header != null) {
			HeaderElement[] elements = header.getElements();
			if (elements != null && elements.length > 0) {
				NameValuePair nv = elements[0].getParameterByName("charset");
				if (nv == null) {
					nv = elements[0].getParameterByName("Charset");
				}
				if (nv != null) {
					return Charset.forName(nv.getValue());
				}
			}
		}
		return null;
	}

	public byte[] getBody() {
		return body;
	}

	@Deprecated
	public void setBody(byte[] body) {
		this.body = body;
	}

	public Charset getCharset() {
		return charset;
	}

	@Deprecated
	public void setCharset(Charset charset) {
		this.charset = charset;
	}

	public Header[] getHeaders() {
		return headers;
	}

	public void setHeaders(Header[] headers) {
		this.headers = headers;
	}
}
